#ifndef _RETRO_SCRIPTMANAGER
#define _RETRO_SCRIPTMANAGER

namespace Retro
{
  namespace Scripting
  {
    class DLLEXPORT NOVTABLE ScriptManager
    {
    private:
      Generic::Vector<ScriptInterface*, 5>  mInterfaces;
      Generic::Vector<ScriptCallback, 50>   mCallbacks;

    public:
      VOID  add(ScriptValue* iValue);
      VOID  add(ScriptValue* iValues, UINT iCount, PCSTR iName);

      INL VOID add(INT iValue, PCSTR iName)
      {
        ScriptValue wValue = { &iValue, TypeInteger, iName };
        add(&wValue);
      }
      INL VOID add(LONG iValue, PCSTR iName)
      {
        ScriptValue wValue = { &iValue, TypeLong, iName };
        add(&wValue);
      }
      INL VOID add(UINT iValue, PCSTR iName)
      {
        ScriptValue wValue = { &iValue, TypeUnsigned, iName };
        add(&wValue);
      }
      INL VOID add(ULONG iValue, PCSTR iName)
      {
        ScriptValue wValue = { &iValue, TypeUnsigned, iName };
        add(&wValue);
      }
      INL VOID add(ULONGLONG iValue, PCSTR iName)
      {
        ScriptValue wValue = { &iValue, TypeUnsigned, iName };
        add(&wValue);
      }
      INL VOID add(FLOAT iValue, PCSTR iName)
      {
        ScriptValue wValue = { &iValue, TypeFloat, iName };
        add(&wValue);
      }
      INL VOID add(DOUBLE iValue, PCSTR iName)
      {
        ScriptValue wValue = { &iValue, TypeDouble, iName };
        add(&wValue);
      }
      INL VOID add(bool iValue, PCSTR iName)
      {
        ScriptValue wValue = { &iValue, TypeBoolean, iName };
        add(&wValue);
      }
      INL VOID add(PCSTR iValue, PCSTR iName)
      {
        ScriptValue wValue = { (PVOID)iValue, TypeString, iName };
        add(&wValue);
      }
      INL VOID add(ScriptCallback iValue, PCSTR iName)
      {
        ScriptValue wValue = { iValue, TypeFunction, iName };
        add(&wValue);
      }
      INL VOID addBool(BOOL iValue, PCSTR iName)
      {
        ScriptValue wValue = { &iValue, TypeBoolean, iName };
        add(&wValue);
      }
      INL VOID addNull(BOOL iValue, PCSTR iName)
      {
        ScriptValue wValue = { &iValue, TypeNull, iName };
        add(&wValue);
      }

      INL BOOL  call(PCSTR iName, Data::ScriptLanguage iLang)
      {
        ScriptInterface* wInterface = getInterface(iLang);
        return wInterface ? wInterface->call(iName) : FALSE;
      }

      INL BOOL  run(PCSTR iScript, Data::ScriptLanguage iLang)
      {
        ScriptInterface* wInterface = getInterface(iLang);
        return wInterface ? wInterface->run(iScript) : FALSE;
      }
      INL BOOL  run(Data::Script* iScript)
      {
        return run(iScript->getBuffer(), iScript->getLanguage());
      }

      INL BOOL  validate(PCSTR iScript, Data::ScriptLanguage iLang)
      {
        ScriptInterface* wInterface = getInterface(iLang);
        return wInterface ? wInterface->validate(iScript) : FALSE;
      }
      INL BOOL  validate(Data::Script* iScript)
      {
        return validate(iScript->getBuffer(), iScript->getLanguage());
      }

      INL ScriptCallback    getCallback(UINT iIndex)
      {
        return mCallbacks[iIndex];
      }
      INL UINT  getCallbackCount()
      {
        return mCallbacks.getLength();
      }

      INL ScriptInterface*  getInterface(UINT iIndex)
      {
        return mInterfaces[iIndex];
      }
      ScriptInterface*      getInterface(Data::ScriptLanguage iLang);

      INL UINT  getInterfaceCount()
      {
        return mInterfaces.getLength();
      }

      ScriptManager();
      ~ScriptManager();
    };
  } // namespace Scripting
} // namespace Retro

#endif
